package task

import (
	"context"
	"errors"
	"fmt"
	"gorm.io/gorm"
	"tupu-go/model"
	"tupu-go/pkg/database"
)

// TaskService 任务服务
type TaskService struct {
	db *gorm.DB
}

// NewTaskService 创建任务服务实例
func NewTaskService() *TaskService {
	return &TaskService{
		db: database.GetDB(),
	}
}

// CreateTask 创建任务（关联关系模型，而非直接关联节点类型）
// 参数：task包含任务基本信息，modelID为关联的关系模型ID
func (s *TaskService) CreateTask(ctx context.Context, task model.Task, modelID int) (*model.Task, error) {
	// 校验：关系模型必须存在
	var modelCount int64
	if err := s.db.WithContext(ctx).
		Model(&model.RelationModel{}).
		Where("id = ?", modelID).
		Count(&modelCount).Error; err != nil {
		return nil, fmt.Errorf("校验关系模型失败: %w", err)
	}
	if modelCount == 0 {
		return nil, errors.New("关联的关系模型不存在")
	}

	// 绑定关系模型
	task.ModelID = modelID

	// 创建任务
	if err := s.db.WithContext(ctx).Create(&task).Error; err != nil {
		return nil, fmt.Errorf("创建任务失败: %w", err)
	}

	return &task, nil
}

// ListTasks 分页获取任务列表（包含关联的关系模型名称）
func (s *TaskService) ListTasks(ctx context.Context, page, pageSize int) ([]model.Task, int64, error) {
	var (
		tasks []model.Task
		total int64
	)

	// 统计总数
	if err := s.db.WithContext(ctx).Model(&model.Task{}).Count(&total).Error; err != nil {
		return nil, 0, fmt.Errorf("统计任务数量失败: %w", err)
	}

	// 分页查询（关联查询关系模型名称）
	offset := (page - 1) * pageSize
	if err := s.db.WithContext(ctx).
		Offset(offset).
		Limit(pageSize).
		Joins("LEFT JOIN relation_models ON tasks.model_id = relation_models.id").
		Select("tasks.*, relation_models.model_name"). // 关联查询模型名称
		Order("tasks.created_at DESC").
		Find(&tasks).Error; err != nil {
		return nil, 0, fmt.Errorf("获取任务列表失败: %w", err)
	}

	return tasks, total, nil
}

// ListTaskNodeTypes 获取任务关联的节点类型（通过关系模型间接获取）
func (s *TaskService) ListTaskNodeTypes(ctx context.Context, taskID string) ([]model.NodeType, error) {
	// 1. 通过任务ID查询关联的关系模型ID
	var task model.Task
	if err := s.db.WithContext(ctx).
		Where("task_code = ?", taskID). // 假设任务唯一标识是task_code
		First(&task).Error; err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil, errors.New("任务不存在")
		}
		return nil, fmt.Errorf("查询任务失败: %w", err)
	}

	// 2. 通过关系模型ID查询关联的节点类型ID
	var modelNodeRelations []model.RelationModelNodeType
	if err := s.db.WithContext(ctx).
		Where("model_id = ?", task.ModelID).
		Find(&modelNodeRelations).Error; err != nil {
		return nil, fmt.Errorf("查询模型节点关联失败: %w", err)
	}
	if len(modelNodeRelations) == 0 {
		return nil, errors.New("该任务关联的模型未配置节点类型")
	}

	// 3. 提取节点类型ID并查询节点类型详情
	nodeTypeIDs := make([]int, 0, len(modelNodeRelations))
	for _, rel := range modelNodeRelations {
		nodeTypeIDs = append(nodeTypeIDs, rel.NodeTypeID)
	}

	var nodeTypes []model.NodeType
	if err := s.db.WithContext(ctx).
		Where("id IN ?", nodeTypeIDs).
		Find(&nodeTypes).Error; err != nil {
		return nil, fmt.Errorf("查询节点类型详情失败: %w", err)
	}

	return nodeTypes, nil
}

// DeleteTask 删除任务（级联删除关联的导入记录等）
func (s *TaskService) DeleteTask(ctx context.Context, taskID string) error {
	return s.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
		// 1. 检查任务是否存在
		var task model.Task
		if err := tx.WithContext(ctx).
			Where("task_code = ?", taskID).
			First(&task).Error; err != nil {
			if errors.Is(err, gorm.ErrRecordNotFound) {
				return errors.New("任务不存在")
			}
			return fmt.Errorf("查询任务失败: %w", err)
		}

		// 2. 删除任务关联的导入记录
		if err := tx.WithContext(ctx).
			Where("task_id = ?", task.ID). // 注意：这里关联的是任务的自增ID
			Delete(&model.ImportRecord{}).Error; err != nil {
			return fmt.Errorf("删除导入记录失败: %w", err)
		}

		// 3. 删除任务本身
		if err := tx.WithContext(ctx).
			Where("task_code = ?", taskID).
			Delete(&model.Task{}).Error; err != nil {
			return fmt.Errorf("删除任务失败: %w", err)
		}

		return nil
	})
}

// UpdateTask 更新任务基本信息（不含关系模型关联）
func (s *TaskService) UpdateTask(ctx context.Context, taskID string, updateData map[string]interface{}) error {
	// 参数校验
	if taskID == "" || len(updateData) == 0 {
		return errors.New("任务ID和更新数据不能为空")
	}

	// 允许更新的字段（不含ModelID，关系模型关联单独更新）
	allowedFields := map[string]bool{
		"task_name":   true,
		"status":      true,
		"description": true,
	}
	filteredData := make(map[string]interface{})
	for k, v := range updateData {
		if allowedFields[k] {
			filteredData[k] = v
		}
	}
	if len(filteredData) == 0 {
		return errors.New("无有效更新字段")
	}

	// 执行更新
	if err := s.db.WithContext(ctx).
		Where("task_code = ?", taskID).
		Updates(filteredData).Error; err != nil {
		return fmt.Errorf("更新任务失败: %w", err)
	}

	return nil
}

// UpdateTaskRelationModel 更新任务关联的关系模型（间接改变节点/边类型）
func (s *TaskService) UpdateTaskRelationModel(ctx context.Context, taskID string, newModelID int) error {
	return s.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
		// 1. 检查任务是否存在
		var taskCount int64
		if err := tx.WithContext(ctx).
			Where("task_code = ?", taskID).
			Count(&taskCount).Error; err != nil {
			return fmt.Errorf("查询任务失败: %w", err)
		}
		if taskCount == 0 {
			return errors.New("任务不存在")
		}

		// 2. 检查新关系模型是否存在
		var modelCount int64
		if err := tx.WithContext(ctx).
			Model(&model.RelationModel{}).
			Where("id = ?", newModelID).
			Count(&modelCount).Error; err != nil {
			return fmt.Errorf("查询新关系模型失败: %w", err)
		}
		if modelCount == 0 {
			return errors.New("新关系模型不存在")
		}

		// 3. 更新任务关联的关系模型
		if err := tx.WithContext(ctx).
			Where("task_code = ?", taskID).
			Update("model_id", newModelID).
			Error; err != nil {
			return fmt.Errorf("更新关系模型关联失败: %w", err)
		}

		return nil
	})
}
